package edu.utn.tacs.grupouno.negocio;

import java.util.Date;
import java.util.Observable;

import javax.jdo.annotations.Extension;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.NotPersistent;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

import edu.utn.tacs.grupouno.exception.TurnoNoDisponibleException;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Turno extends Observable {
	private Long id;
	
	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY, column = "id")
	@Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
	@XmlAttribute(name="key")
	private String encodedKey;
	
	private Analisis analisis;

	@Persistent
	@XmlElement
	private String analisisId;

	@Persistent
	@XmlElement
	private TurnoSemanal turnoSemanal;
	
	@NotPersistent
	@XmlTransient
	private EstadoTurno estado;
	
	/** Solo para el datastore */
	@Persistent
	@XmlElement
	private Date fecha;
	
	public Turno() {
	}
	
	public Turno(TurnoSemanal turnoSemanal) {
		this.turnoSemanal = turnoSemanal;
	}
	
	public boolean isDisponible() {
		return estado.isDisponible();
	}
	/**
	 * Se pueden asignar un paciente si esta disponible en cuyo caso pasara al estado Asignado<br>
	 * Si el turno ya fue asignado y se intenta asignar otro paciente tira TurnoNoDisponibleException<br>
	 * Si el turno ya fue asignado a un paciente y el parametro paciente es el mismo paciente, entonces<br>
	 *   se asignara a este turno el nuevo analisis por parametro.
	 * El parametro analisis es opcional si se envia null no se asiganara analisis al turno o se eliminara el actual
	 * @param analisis
	 * @throws TurnoNoDisponibleException si el turno ya esta asignado a otro paciente
	 */
	public void asignar(Analisis analisis) {
		if(isDisponible()) {
			this.setAnalisis(analisis);
			this.setEstado(new AsignadoEstadoTurno());
		} else {
			throw new TurnoNoDisponibleException();
		}
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}
	
	public void setAsistioPaciente() {
		estado = new AsistioEstadoTurno();
		setChanged();
		notifyObservers();
	}
	
	public void setNoAsistioPaciente() {
		estado = new NoAsistioPacienteEstadoTurno();
	}
	
	public boolean pacienteAsistio() {
		return estado.pacienteAsistio();
	}
	
	public void setAnalisis(Analisis analisis) {
		this.analisis = analisis;
		this.analisisId = analisis.getId().toString();
	}
	
	public Analisis getAnalisis() {
		return analisis;
	}

	public String getAnalisisId() {
		if((analisisId == null || analisisId.equals("")) && analisis != null) {
			analisisId = analisis.getId().toString();
		}
		return analisisId;
	}

	public void setAnalisisId(String analisisId) {
		this.analisisId = analisisId;
	}

	public void setTurnoSemanal(TurnoSemanal turnoSemanal) {
		this.turnoSemanal = turnoSemanal;
	}
	
	public TurnoSemanal getTurnoSemanal() {
		return turnoSemanal;
	}
	
	public String getHorario() {
		if(turnoSemanal != null) {
			return turnoSemanal.getHorario();
		}
		return null;
	}
	
	@XmlTransient
	public EstadoTurno getEstado() {
		return estado;
	}

	public void setEstado(EstadoTurno estado) {
		this.estado = estado;
	}
	
	@XmlElement(name="estado")
	@Persistent(name="estado")
	public String getEstadoAsString() {
		if(estado == null) {
			return "null";
		}
		String str = estado.getClass().toString();
		str = str.substring(str.lastIndexOf(".") + 1);
		return str;
	}

	public void setEstadoAsString(String estado) {
		if(estado == null || estado.equals("null")) {
			estado = null;
		} else if(estado.equals("AsignadoEstadoTurno")) {
			this.estado = new AsignadoEstadoTurno();
		} else if(estado.equals("AsistioEstadoTurno")) {
			this.estado = new AsistioEstadoTurno();
		} else if(estado.equals("DisponibleEstadoTurno")) {
			this.estado = new DisponibleEstadoTurno();
		} else if(estado.equals("NoAsistioPacienteEstadoTurno")) {
			this.estado = new NoAsistioPacienteEstadoTurno();
		}
	}

	public void setFecha(Date fecha) {
		this.fecha = fecha;
	}

	public Date getFecha() {
		return fecha;
	}

	public void setEncodedKey(String encodedKey) {
		this.encodedKey = encodedKey;
	}
	@XmlTransient
	public String getEncodedKey() {
		return encodedKey;
	}
	
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder("{\n");
		sb.append("\tfecha: '").append(getFecha()).append("',\n");
		sb.append("\tturnoSemanal: '").append(getTurnoSemanal()).append("',\n");
		sb.append("\testado: '").append(getEstadoAsString()).append("',\n");
		sb.append("\tanalisisId: '").append(getAnalisisId()).append("'\n}");
		return sb.toString();
	}
}